/**
 * 图片处理工具类
 * 提供图片压缩、格式转换等功能
 */

/**
 * 压缩图片
 * @param {File} file - 原始图片文件
 * @param {Object} options - 压缩配置选项
 * @param {number} options.maxWidth - 最大宽度，默认1920
 * @param {number} options.maxHeight - 最大高度，默认1080
 * @param {number} options.quality - 压缩质量(0-1)，默认0.8
 * @param {string} options.outputFormat - 输出格式，默认为原格式
 * @returns {Promise<File>} - 返回压缩后的文件对象
 */
export function compressImage(file, options = {}) {
  return new Promise((resolve, reject) => {
    // 默认配置
    const config = {
      maxWidth: 1920,
      maxHeight: 1080,
      quality: 0.8,
      outputFormat: file.type,
      ...options
    }

    // 验证文件类型
    if (!file.type.startsWith('image/')) {
      reject(new Error('文件类型不是图片'))
      return
    }

    // 创建FileReader读取图片
    const reader = new FileReader()
    reader.onload = (e) => {
      const img = new Image()
      img.onload = () => {
        // 创建canvas进行压缩
        const canvas = document.createElement('canvas')
        const ctx = canvas.getContext('2d')

        // 计算压缩后的尺寸
        const { width, height } = calculateCompressedSize(
          img.width,
          img.height,
          config.maxWidth,
          config.maxHeight
        )

        // 设置canvas尺寸
        canvas.width = width
        canvas.height = height

        // 绘制压缩后的图片
        ctx.drawImage(img, 0, 0, width, height)

        // 转换为Blob对象
        canvas.toBlob((blob) => {
          // 创建新的File对象
          const compressedFile = new File([blob], file.name, {
            type: config.outputFormat,
            lastModified: Date.now()
          })

          // 添加压缩信息到文件对象
          compressedFile.originalSize = file.size
          compressedFile.compressedSize = blob.size
          compressedFile.compressionRatio = ((file.size - blob.size) / file.size * 100).toFixed(2)

          resolve(compressedFile)
        }, config.outputFormat, config.quality)
      }

      img.onerror = () => {
        reject(new Error('图片加载失败'))
      }

      img.src = e.target.result
    }

    reader.onerror = () => {
      reject(new Error('文件读取失败'))
    }

    reader.readAsDataURL(file)
  })
}

/**
 * 计算压缩后的图片尺寸
 * @param {number} originalWidth - 原始宽度
 * @param {number} originalHeight - 原始高度
 * @param {number} maxWidth - 最大宽度
 * @param {number} maxHeight - 最大高度
 * @returns {Object} - 包含width和height的对象
 */
function calculateCompressedSize(originalWidth, originalHeight, maxWidth, maxHeight) {
  let { width, height } = { width: originalWidth, height: originalHeight }

  // 如果图片尺寸小于最大尺寸，不需要压缩
  if (width <= maxWidth && height <= maxHeight) {
    return { width, height }
  }

  // 计算缩放比例
  const widthRatio = maxWidth / width
  const heightRatio = maxHeight / height
  const ratio = Math.min(widthRatio, heightRatio)

  // 计算新尺寸
  width = Math.round(width * ratio)
  height = Math.round(height * ratio)

  return { width, height }
}

/**
 * 批量压缩图片
 * @param {File[]} files - 图片文件数组
 * @param {Object} options - 压缩配置选项
 * @param {Function} onProgress - 进度回调函数
 * @returns {Promise<File[]>} - 返回压缩后的文件数组
 */
export function compressImages(files, options = {}, onProgress = null) {
  // eslint-disable-next-line no-async-promise-executor
  return new Promise((resolve, reject) => {
    (async () => {
      try {
        const compressedFiles = []
        const total = files.length

        for (let i = 0; i < total; i++) {
          const file = files[i]

          // 跳过非图片文件
          if (!file.type.startsWith('image/')) {
            compressedFiles.push(file)
            continue
          }

          try {
            const compressedFile = await compressImage(file, options)
            compressedFiles.push(compressedFile)
          } catch (error) {
            // 压缩失败时使用原文件
            compressedFiles.push(file)
          }

          // 调用进度回调
          if (onProgress && typeof onProgress === 'function') {
            onProgress({
              current: i + 1,
              total: total,
              progress: Math.round(((i + 1) / total) * 100)
            })
          }
        }

        resolve(compressedFiles)
      } catch (error) {
        reject(error)
      }
    })()
  })
}

/**
 * 获取图片信息
 * @param {File} file - 图片文件
 * @returns {Promise<Object>} - 返回图片信息对象
 */
export function getImageInfo(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.onload = (e) => {
      const img = new Image()
      img.onload = () => {
        resolve({
          width: img.width,
          height: img.height,
          size: file.size,
          type: file.type,
          name: file.name
        })
      }
      img.onerror = () => {
        reject(new Error('无法获取图片信息'))
      }
      img.src = e.target.result
    }
    reader.onerror = () => {
      reject(new Error('文件读取失败'))
    }
    reader.readAsDataURL(file)
  })
}

/**
 * 格式化文件大小
 * @param {number} bytes - 字节数
 * @returns {string} - 格式化后的文件大小
 */
export function formatFileSize(bytes) {
  if (bytes === 0) return '0 Bytes'

  const k = 1024
  const sizes = ['Bytes', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))

  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}